package routes

import (
	"github.com/garyburd/redigo/redis"
	"github.com/martini-contrib/render"
	"log"
	"net/http"
	"rhelper"
	"strconv"
	"strings"
	"task"
)

func GetTasks(r render.Render, req *http.Request) {
	var a = req.URL.Query().Get("a")
	var farmId = req.URL.Query().Get("farmId")
	var taskId = req.URL.Query().Get("taskId")
	conn := rhelper.Pool().Get()
	defer conn.Close()

	type Task struct {
		Name string `json:"name"`
		Id   string `json:"id"`
	}

	type ExtValue struct {
		Account string
		FarmId  string
		TaskId  string
	}

	var tasks []Task = nil
	var taskIdArray []string
	var i int = 0
	taskIds, err := redis.String(conn.Do("HGET", rhelper.FarmHash+farmId, "tasks"))
	if err != nil {
		log.Println("get tasks err:", err)
	}

	if taskIds == "" || err != nil {
		log.Println("no tasks configure for farm:", farmId)
		goto OUT
	}

	if strings.Contains(taskIds, ",") {
		taskIdArray = strings.Split(taskIds, ",")
	} else {
		taskIdArray = []string{taskIds}
	}

	tasks = make([]Task, len(taskIdArray))

	for _, id := range taskIdArray {
		fields, err := redis.Strings(conn.Do("HMGET", rhelper.TaskHash+id, "id", "name"))
		if err == nil && fields[0] != "" {
			var t = &tasks[i]
			t.Id = fields[0]
			t.Name = fields[1]
			i++
		}
	}

	tasks = tasks[0:i]
OUT:
	ev := ExtValue{Account: a, TaskId: taskId, FarmId: farmId}
	r.HTML(200, "taskMgr", TmplValue{Title: "Account manange", ExtValue: tasks, ExtValue2: ev})
}

func commaString2Array(src string) []string {
	if src == "" {
		return []string{}
	}

	var result []string
	if strings.Contains(src, ",") {
		result = strings.Split(src, ",")
	} else {
		result = []string{src}
	}

	return result
}

func commaStringContain(src string, substr string) bool {
	result := commaString2Array(src)
	for _, a := range result {
		if a == substr {
			return true
		}
	}
	return false
}

func GetTaskInfo(r render.Render, req *http.Request) {
	var taskId = req.URL.Query().Get("taskId")
	conn := rhelper.Pool().Get()
	defer conn.Close()

	type Task struct {
		Err         string   `json:"err"`
		Name        string   `json:"name"`
		Id          string   `json:"id"`
		Description string   `json:"description"`
		Account     string   `json:"account"`
		Farm        string   `json:"farm"`
		Type        string   `json:"type"`
		Duration    string   `json:"duration"`
		PerBatch    string   `json:"perbatch"`
		Status      string   `json:"status"`
		AO          []string `json:"ao"`
		AC          []string `json:"ac"`
		Pumps       []string `json:"pumps"`
		Valves      []string `json:"valves"`
	}

	var t Task = Task{}
	taskInfos, err := redis.Strings(conn.Do("HMGET", rhelper.TaskHash+taskId, "name", "id", "description", "account", "farm",
		"type", "duration", "perbatch", "ao", "ac", "pump", "vv"))
	if err != nil {
		t.Err = err.Error()
		r.JSON(200, t)
		return
	}

	if len(taskInfos) < 1 || taskInfos[0] == "" {
		t.Err = "not found task:" + taskId
		r.JSON(200, t)
		return
	}

	t.Name = taskInfos[0]
	t.Id = taskInfos[1]
	t.Description = taskInfos[2]
	t.Account = taskInfos[3]
	t.Farm = taskInfos[4]
	t.Type = taskInfos[5]
	t.Duration = taskInfos[6]
	t.PerBatch = taskInfos[7]
	t.AO = commaString2Array(taskInfos[8])
	t.AC = commaString2Array(taskInfos[9])
	t.Pumps = commaString2Array(taskInfos[10])
	t.Valves = commaString2Array(taskInfos[11])

	if task.Mgr.IsTaskRunning(t.Id) {
		t.Status = "running"
	} else {
		t.Status = "stop"
	}
	r.JSON(200, t)
}

func EditTask(r render.Render, req *http.Request) {
	var farmId = req.URL.Query().Get("farmId")
	var account = req.URL.Query().Get("a")
	var taskId = req.URL.Query().Get("taskId")
	conn := rhelper.Pool().Get()
	defer conn.Close()

	if taskId == "" || farmId == "" || account == "" {
		r.Error(404)
		return
	}

	type Task struct {
		Id          string
		Account     string
		Farm        string
		Name        string
		Description string
		Type        string
		Duration    string
		PerBatch    string
		IsNew       bool
	}

	var task Task = Task{}

	if taskId == "newTask" {
		newId, _ := redis.Int(conn.Do("INCR", rhelper.TaskIdHolder))
		task.IsNew = true
		task.Id = strconv.FormatInt(int64(newId), 10)
		task.Account = account
		task.Farm = farmId

	} else {
		task.IsNew = false
		fields, err := redis.Strings(conn.Do("HMGET", rhelper.TaskHash+taskId, "id", "account", "name", "description",
			"farm", "type", "perbatch", "duration"))
		if err != nil {
			log.Println(err)
		}
		task.Id = fields[0]
		task.Account = fields[1]
		task.Name = fields[2]
		task.Description = fields[3]
		task.Farm = fields[4]
		task.Type = fields[5]
		task.PerBatch = fields[6]
		task.Duration = fields[7]
	}

	r.HTML(200, "taskEdit", TmplValue{Title: "task edit", ExtValue: task})
}

type TaskEditValue struct {
	Id          string `form:"textinput-taskId" json:"id,omitempty"`
	Account     string `form:"textinput-taskAccount" json:"account,omitempty"`
	Name        string `form:"textinput-taskName" json:"name,omitempty"`
	Description string `form:"textinput-taskDesc" json:"description,omitempty"`
	Farm        string `form:"textinput-taskFarm"`
	Type        string `form:"textinput-taskType"`
	PerBatch    string `form:"textinput-taskBatch"`
	Duration    string `form:"textinput-taskDuration"`
}

func SaveTask(taskValue TaskEditValue) string {

	conn := rhelper.Pool().Get()
	defer conn.Close()

	tasks, _ := redis.String(conn.Do("HGET", rhelper.FarmHash+taskValue.Farm, "tasks"))
	if len(tasks) < 1 {
		tasks = taskValue.Id
	} else {
		if !commaStringContain(tasks, taskValue.Id) {
			tasks = tasks + "," + taskValue.Id
		}
	}

	conn.Send("MULTI")
	conn.Send("HMSET", rhelper.TaskHash+taskValue.Id,
		"id", taskValue.Id, "account", taskValue.Account, "name", taskValue.Name, "description", taskValue.Description,
		"farm", taskValue.Farm, "type", taskValue.Type, "perbatch", taskValue.PerBatch, "duration", taskValue.Duration)
	conn.Send("HSET", rhelper.FarmHash+taskValue.Farm, "tasks", tasks)
	_, err := conn.Do("EXEC")
	if err != nil {
		log.Println(err)
		return err.Error()
	}

	return "ok"
}

func AddTaskController(r render.Render, req *http.Request) {
	var farmId = req.URL.Query().Get("farmId")
	var account = req.URL.Query().Get("a")
	var taskId = req.URL.Query().Get("taskId")
	var ctype = req.URL.Query().Get("ctype")

	if taskId == "" || farmId == "" || account == "" {
		r.Error(404)
		return
	}

	type Task struct {
		Id      string
		Account string
		Farm    string
		CType   string
	}

	var task Task = Task{Id: taskId, Account: account, Farm: farmId, CType: ctype}
	r.HTML(200, "taskControllerAdd", TmplValue{Title: "task edit", ExtValue: task})
}

func CheckTaskController(r render.Render, req *http.Request) string {
	var controllerId = req.URL.Query().Get("textinput-taskController")
	//var ctype = req.URL.Query().Get("ctype")
	var farmId = req.URL.Query().Get("farmId")

	conn := rhelper.Pool().Get()
	defer conn.Close()

	id, err := redis.String(conn.Do("HGET", rhelper.ControllerHash+controllerId, "id"))
	if err != nil {
		log.Println(err)
		return err.Error()
	}

	if id == "" {
		return "no such controller:" + controllerId
	}

	farmControllerIds, err := redis.String(conn.Do("HGET", rhelper.FarmHash+farmId, "controllers"))
	if err != nil {
		log.Println(err)
		return err.Error()
	}

	if !commaStringContain(farmControllerIds, controllerId) {
		return "farm not has controller " + controllerId
	}

	return "true"
}

type TaskControllerEditValue struct {
	Id           string `form:"textinput-taskId" json:"id,omitempty"`
	Account      string `form:"textinput-taskAccount" json:"account,omitempty"`
	Farm         string `form:"textinput-taskFarm" json:"farm,omitempty"`
	CType        string `form:"textinput-taskCType" json:"ctype,omitempty"`
	ControllerId string `form:"textinput-taskController" json:"controller,omitempty"`
}

func SaveTaskController(taskValue TaskControllerEditValue) string {
	if taskValue.Id == "" {
		return "invalid parameter"
	}

	conn := rhelper.Pool().Get()
	defer conn.Close()

	controllers, err := redis.String(conn.Do("HGET", rhelper.TaskHash+taskValue.Id, taskValue.CType))
	if err != nil {
		controllers = ""
	}

	if len(controllers) > 0 {
		if !commaStringContain(controllers, taskValue.ControllerId) {
			controllers = controllers + "," + taskValue.ControllerId
		}
	} else {
		controllers = taskValue.ControllerId
	}

	_, err = conn.Do("HSET", rhelper.TaskHash+taskValue.Id, taskValue.CType, controllers)
	if err != nil {
		return err.Error()
	}

	return "ok"
}

func DelTaskControllers(req *http.Request) string {
	err := req.ParseForm()
	if err != nil {
		log.Println(err)
		return err.Error()
	}

	conn := rhelper.Pool().Get()
	defer conn.Close()

	var taskId = req.Form.Get("taskId")
	var ctype = req.Form.Get("ctype")
	var ids = req.Form.Get("ids")

	if taskId == "" {
		return "invalid parameter"
	}

	var idarray []string
	if strings.Contains(ids, ",") {
		idarray = strings.Split(ids, ",")
	} else {
		idarray = []string{ids}
	}

	controllers, err := redis.String(conn.Do("HGET", rhelper.TaskHash+taskId, ctype))
	var controllersArray []string
	if strings.Contains(controllers, ",") {
		controllersArray = strings.Split(controllers, ",")
	} else {
		controllersArray = []string{controllers}
	}

	newControllersArray := make([]string, len(controllersArray))
	var newControllerIndex = 0
	for _, a := range controllersArray {
		var deleted bool = false
		for _, b := range idarray {
			if a == b {
				deleted = true
				break
			}
		}

		if !deleted {
			newControllersArray[newControllerIndex] = a
			newControllerIndex++
		}
	}

	newControllersArray = newControllersArray[0:newControllerIndex]
	newControllers := ""
	if len(newControllersArray) > 0 {
		newControllers = newControllersArray[0]
		for i := 1; i < len(newControllersArray); i++ {
			newControllers = newControllers + "," + newControllersArray[i]
		}
	}

	if len(newControllers) < 1 {
		_, _ = conn.Do("HDEL", rhelper.TaskHash+taskId, ctype)
	} else {
		_, _ = conn.Do("HSET", rhelper.TaskHash+taskId, ctype, newControllers)
	}
	return "ok"
}
